import type {UseFetchOptions} from '#app'
import type {_AsyncData} from '#app/composables/asyncData'
import type {MaybeRef, Ref} from 'vue'
import type {FetchContext} from 'ofetch'
import type {ApiError} from './error'

export interface ApiOptionalParamTy<T> extends Number {}
export interface ApiRequiredParamTy<T> extends String {}
export interface ApiRespTy<T> extends String {}
export interface ApiOptions<R = any, P = any> extends Omit<UseFetchOptions<P>, 'params' | 'query' | 'body'> {
    url: string
    paramTy?: ApiOptionalParamTy<P> | ApiRequiredParamTy<P>
    respTy?: ApiRespTy<R>
}
export interface RequiredParamsApiOptions<R, P> extends ApiOptions<R, P> {
    paramTy: ApiRequiredParamTy<P>
}
export interface OptionalParamsApiOptions<R, P> extends ApiOptions<R, P> {
    paramTy?: ApiOptionalParamTy<P>
}

export interface RespWarp<R> {
    data: R
    code: number
    message: string
}

export interface RequiredParamsApi<R, P> {
    fetch(params: P): Promise<RespWarp<R> | null>
    useFetch(params: MaybeRef<P>): Promise<[Ref<R>, _AsyncData<RespWarp<R>, any>]>
}

export interface OptionalParamsApi<R, P> {
    fetch(params?: P): Promise<RespWarp<R> | null>
    useFetch(params?: MaybeRef<P>): Promise<[Ref<R>, _AsyncData<RespWarp<R>, any>]>
}

export interface DefineApi {
    <R = any, P = any>(options: OptionalParamsApiOptions<R, P>): OptionalParamsApi<R, P>
    <R = any, P = any>(options: RequiredParamsApiOptions<R, P>): RequiredParamsApi<R, P>
}

export type ApiHandler = {
    onRequest?:(ctx: FetchContext) => Promise<void>
    onResponse?: (ctx: FetchContext) => Promise<void>
    onError?: (err: ApiError) => Promise<void>
}
export interface DefaultApiOptions extends ApiHandler {
    baseURL?: string
}
